<?php
/* Kammerath Network Website System */
require_once("config.php");

// external lib: Opauth lib for authentication
require_once("lib/Opauth/Opauth.php");

// external lib: Smarty Template Engine
require_once("lib/Smarty/Smarty.class.php");

// external lib: Minify Classes incl. JSMin
require_once("lib/Minify/JSMin.class.php");
require_once("lib/Minify/Minify_HTML.class.php");
require_once("lib/Minify/Minify_Javascript.class.php");

// application internal classes
require_once("class/cache.class.php");
require_once("class/database.class.php");
require_once("class/crypto.class.php");
require_once("class/email.class.php");
require_once("class/user.class.php");
require_once("class/blog.class.php");
require_once("class/search.class.php");
require_once("class/amazon.class.php");
require_once("class/analytics.class.php");
require_once("class/minify.class.php");

// create and instance of the blog
// which requires the domain as a param
// to determine the site to use
$b = new blog($_SERVER["HTTP_HOST"]);

/* check if the host name requested is the 
 * primary host name and not one of the CDN 
 * host names */
if($_SERVER["HTTP_HOST"]!=CONFIG_CDN_PRIMARY_DOMAIN){
	// 301 redirect and exit, when it is not 
	// the primary domain name and make sure
	// it is redirecting to the same page requested	
	header("HTTP/1.1 301 Moved Permanently");
	header("Location: http://"
			.CONFIG_CDN_PRIMARY_DOMAIN
			.$_SERVER["REQUEST_URI"]); 
	
	// exists the this request
	exit();
}

// instanciate the template engine
$template = new Smarty();

// define the is_admin var
$is_admin = false;

// indicator whether the request
// should get a 404 response
$is_404 = false;

/* indicates whether a comment was 
 * just posted with this request or not. 
 * This info will be passed directly to 
 * the analytics*/
$comment_posted = false;

/* notification message will be shown in the notification bar 
	when not empty, otherwise it can be ignored. The codes are
	handled in the template */
$notificiationMessageCode = "";

// every page needs the category list
$categoryPublishedList = $b->db->getCategoryPublishedList();

// initialize google analytics
$ga = new analytics();

/* get the user data, if logged in */
$u = $b->getUser();
$userSingleSignOnKey = "";
$userAuthProvider = "";
if($u->isLoggedIn()){	
	if($u->isAdmin()){
		$is_admin = true;
	}
	
	// assign the user to the template
	$template->assign("user",$u->getUserInfo());	

	// set the auth provider
	$userAuthProvider = $u->getUserInfo()["authprovider"];

	// set the single sign on key
	$userSingleSignOnKey = $u->getAuthKey();
}

// assign the single sign on key to the template
$template->assign("singlesignonkey",$userSingleSignOnKey);

// get all available domains and assign them
$domainList = $b->db->getPrimaryDomainList();
$template->assign("domainList",$domainList);

/* define the page type and use 404 as 
 * the default page type as it will show
 * as default when no other page matches */
$pageType = "404";
$pageItem = "404";
if(strpos($_SERVER["REQUEST_URI"],"index.php")==1){
	// its also index, when its index.php
	$pageType = "index";
	$pageItem = "index";
}else{
	if(array_key_exists("type", $_GET)==true
		&&array_key_exists("item", $_GET)==true){
		// page and item definition are present
		$pageType = $_GET["type"];
		$pageItem = $_GET["item"];
	}
}

/* check for email opt-in request in post variables */
if(array_key_exists("subscriber_email_address", $_POST)){
	$e = $b->getEmail();

	/* validate the e-mail address and send request */
	$subscriberEmail = $_POST["subscriber_email_address"];
	if($e->validateEmailAddress($subscriberEmail)){
		$e->sendOptIn($subscriberEmail);
		$notificiationMessageCode = "EMAIL_OPTIN_SENT";
	}
}

/* when the page type is index or category,
 * we need the list of articles */
if($pageType=="index"){
	// get the month for the top articles
	$topArticleMonth = $ga->getReportingMonth();
	
	// declare the top article list
	$topArticleList = array();
	
	// get the raw top articles
	$topArticleListRaw = $ga->getCachedThisMonthsTopArticles
								($topArticleMonth["number"]);

	// take ten pages at max
	if(count($topArticleListRaw)>10){
		$ta_keys = array_keys($topArticleListRaw);
		for($tp=0;$tp<10;$tp++){
			// copy them, one by one
			$topArticleList[$tp] = $topArticleListRaw[$ta_keys[$tp]];
		}
	}else{
		// if its less or equal ten, take them
		$topArticleList = $topArticleListRaw;
	}
	
	// assign the top articles for the homepage
	$template->assign("thisTopArticleMonth",$topArticleMonth["name"]);
	$template->assign("thisMonthTopArticleList",$topArticleList);
	
	// assign the articles for the home page
	$template->assign("articleList",$b->getLatestArticles(20));
}if($pageType=="search"){
	// instanciate the search class
	$s = new search($_SERVER["HTTP_HOST"]);
	
	// get the keyword and replace the - character
	// as it represents a space the user entered and
	// is just used for clean url creation
	$q = str_replace("-", " ", $_GET["item"]);
	
	// measure search execution time
	$s_starttime = microtime(true);

	// execute the search
	$searchResult = $s->searchSite($q);

	// measure search execution time
	$s_exectime = round((microtime(true)-$s_starttime),4);

	// assign the key word and the result
	$template->assign("searchExecutionTime",$s_exectime);
	$template->assign("searchQuery",$q);
	$template->assign("searchResult",$searchResult);
}if($pageType=="category"){
	// if the category item does not exist
	// we need to show the 404 page
	$cat_found = false;
	for($cl=0;$cl<count($categoryPublishedList);$cl++){
		if($categoryPublishedList[$cl]["url"]==$pageItem){
			$cat_found = true;
		}
	}
	
	// set the 404 flag, when category does not exists
	if(!$cat_found){$is_404=true;}
	
	$pageCategoryItem = $b->getCategory($pageItem);

	$template->assign("pageCategoryItem",$pageCategoryItem);
	$template->assign("articleList",$b->getCategoryArticles($pageItem));
}if($pageType=="article"){
	// get the article and its comments
	$preview_mode = false;
	if(array_key_exists("p", $_GET)){
		$preview_mode = true;
	}
	$pageArticle = $b->getArticle($pageItem,$preview_mode);
	$pageComments = $b->db->getArticleCommentList($pageItem);
		
	// set the 404 indicator when the article is null
	if($pageArticle==null){
		// set the indicator
		$is_404 = true;
	}else{
		/* check for a deletion request */
		if(array_key_exists("deleteComment", $_POST)){
			if($u->isLoggedIn()){
				$delete_comment_id = $_POST["deleteComment"];
				
				// set author indicator to false by default
				$is_comment_author = false;
				
				// check if the user is author
				for($cm=0;$cm<count($pageComments);$cm++){
					if($pageComments[$cm]["id"]==$delete_comment_id
						&& $pageComments[$cm]["user_extid"]==$u->getExtId()){
						// this user is author of the comment
						$is_comment_author = true;
					}
				}
				
				// delete when the user is admin or author
				if($is_admin==true || $is_comment_author==true){
					// finally delete the comment
					$b->db->deleteComment($delete_comment_id);

					// set the notification to comment posted
					$notificiationMessageCode = "COMMENT_DELETED";
					
					// update the page comments
					$pageComments = $b->db->getArticleCommentList($pageItem);
				}
			}
		}
		
		/* check if a comment is in the post vars */
		if(array_key_exists("comment", $_POST)){
			if($u->isLoggedIn()){				
				// finally add the comment
				$b->db->addComment($u->getExtId(), 
					$_GET["item"], $_POST["comment"]);

				// send an e-mail when a new comment arrived
				$b->getEmail()->sendNewCommentNotification($pageArticle["url"],
													$pageArticle["title"],
													$u->getUserInfo()["realname"],
													$u->getUserInfo()["imageurl"],
													$_POST["comment"]);
					
				// set the indicator to true
				$comment_posted = true;

				// set the notification to comment posted
				$notificiationMessageCode = "COMMENT_POSTED";
					
				// update the page comments
				$pageComments = $b->db->getArticleCommentList($pageItem);
			}
		}
		
		// get the page recommendations
		$analyticsPage = "/".$pageItem.".html";
		
		// retrieve the recommendations cached
		$recommendationList = $ga->getCachedRecommendations($analyticsPage);

		// get the amazon book suggestions 
		// for this article when a keyword
		// was provided
		$bookOffers = array();

		if(strlen($pageArticle["keyword"])>0){
			// instanciate the amazon api wrapper class
			$amzn = new amazon($b->db->getLanguageCode());
			// perform an item search in the books category
			$bookOffers = $amzn->itemSearchCached
					($pageArticle["keyword"], "Books");
		}
		// assign both the article and the
		// comment list to the template
		$template->assign("bookOffers",$bookOffers);
		$template->assign("article",$pageArticle);
		$template->assign("commentList",$pageComments);
		$template->assign("recommendationList",$recommendationList);
	}
}if($pageType=="newsletter"){
	// newsletter data variables
	$newsletter_emailaddress = "";
	$newsletter_gender = 0;
	$newsletter_fullname = "";
	$newsletter_phonenumber = "";
	$newsletter_mode = "new";

	// get the e-mail object
	$e = $b->getEmail();

	/* newsletter signup and profile management page */
	if(array_key_exists("emailaddress", $_POST)==true
		&&array_key_exists("gender", $_POST)==true
		&&array_key_exists("fullname", $_POST)==true
		&&array_key_exists("phonenumber", $_POST)==true
		&&array_key_exists("g-recaptcha-response", $_POST)==true){
		// check the validity of the captcha code
		$contactCaptchValid = false;
		if(crypto::validateRecaptcha($_POST["g-recaptcha-response"])){
			$contactCaptchValid = true;
		}

		/* send a confirmation opt-in e-mail when the user
			is not authenticated through an optin key. If the
			user is authenticated through a key then update
			the data directly */
		$subscriber_authenticated = false;
		if(array_key_exists("optinkey", $_GET)){
			// read below, the key requires a fix
			// due to the transport as get param
			$optinKey = str_replace(" ", "+", $_GET["optinkey"]);
			$optinKeyData = $e->decryptOptInToken($optinKey);
			if($optinKeyData!=""){
				// the key is valid, now check if the key's email
				// address matches the one posted
				if($optinKeyData->email==$_POST["emailaddress"]){
					// when it does, auth is successful
					$subscriber_authenticated = true;
				}
			}

			// only process the request when the captcha is valid
			if($contactCaptchValid){
				// immediately update the database
				// when already authenticated
				if($subscriber_authenticated){
					if($e->updateSubscriber($_POST["gender"],$_POST["fullname"],
										$_POST["emailaddress"],$_POST["phonenumber"])){
						// update the notification
						$notificiationMessageCode = "SUBSCRIPTION_UPDATED";

						// update the template vars
						$newsletter_emailaddress = $_POST["emailaddress"];
						$newsletter_gender = intval($_POST["gender"]);
						$newsletter_fullname = $_POST["fullname"];
						$newsletter_phonenumber = $_POST["phonenumber"];
						$newsletter_mode = "edit";
					}else{
						$notificiationMessageCode = "SUBSCRIPTION_UPDATE_FAILED";
					}
				}else{
					// if not, then send the opt-in request
					$e->sendOptIn($_POST["emailaddress"],$_POST["fullname"],
									$_POST["gender"],$_POST["phonenumber"]);
					
					if($b->db->isExistingSubscriber($_POST["emailaddress"])){
						$notificiationMessageCode = "EMAIL_UPDATECONFIRM_SENT";
					}else{
						$notificiationMessageCode = "EMAIL_OPTIN_SENT";
					}
				}
			}else{
				// set notification to captcha failure
				$notificiationMessageCode = "EMAIL_SUBSCRIPTION_CAPTCHA_FAILURE";
			}
		}
	}else{
		/* check for email op-in confirmation code */
		if(array_key_exists("optinkey", $_GET)==true
			&&strlen($_GET["optinkey"])>0){
			if($_GET["optinkey"]!="edit"){
				/* the fact that the key is being passed in the querystring
					means it is being url decoded by php which will cause 
					problems with decoding the base64 data. Therefore we 
					need to urlencode() it here again */
				$optinKey = str_replace(" ", "+", $_GET["optinkey"]);

				/* get the newsletter data from the key */
				$newsletterData = $e->decryptOptInToken($optinKey);
				if($newsletterData==""){
					$notificiationMessageCode = "INVALID_OPTINTOKEN";				
				}else{
					// assign the token data to the template variables
					$newsletter_emailaddress = $newsletterData->email;
					$newsletter_gender = intval($newsletterData->gender);
					$newsletter_fullname = $newsletterData->fullname;
					$newsletter_phonenumber = $newsletterData->phone;
					$newsletter_mode = "edit";

					// update the notification message
					if(!$newsletterData->isSubscriptionUpdate){
						$notificiationMessageCode = "SUBSCRIPTION_SUCCESSFUL";
					}else{
						$notificiationMessageCode = "SUBSCRIPTION_UPDATED";
					}
				}
			}else{
				// set initial edit mode
				$newsletter_mode = "edit";
			}
		}else{
			/* check if there is a final unsubscribe code */
			if(array_key_exists("unsubscribe", $_GET)==true
				&&$_GET["unsubscribe"]!=""){
				// unsubscribe the email address
				$unsubscribeToken = str_replace(" ", "+", $_GET["unsubscribe"]);
				$unsubscribeResult = $e->unsubscribe($unsubscribeToken);

				// check the unsubscribe result and define the notification
				if($unsubscribeResult){
					$notificiationMessageCode = "UNSUBSCRIBE_SUCCESSFUL";
				}else{
					$notificiationMessageCode = "UNSUBSCRIBE_FAILED";
				}
			}
		}	

		/* check if there is an unsubscribe request */
		if(array_key_exists("unsubscribe_email", $_POST)){
			if($e->sendUnsubscribe($_POST["unsubscribe_email"])){
				$notificiationMessageCode = "UNSUBSCRIBE_REQUEST_SUCCESSFUL";
			}else{
				$notificiationMessageCode = "UNSUBSCRIBE_REQUEST_FAILED";
			}
		}	
	}

	// assign the variables to the template
	$template->assign("newsletter_emailaddress",$newsletter_emailaddress);
	$template->assign("newsletter_gender",$newsletter_gender);
	$template->assign("newsletter_fullname",$newsletter_fullname);
	$template->assign("newsletter_phonenumber",$newsletter_phonenumber);
	$template->assign("newsletter_mode",$newsletter_mode);
}if($pageType=="contact"){
	/* process contact requests and ensure that the mandatory
		fields exist in the post variables.  */
	if(array_key_exists("contactname", $_POST)==true
		&&array_key_exists("contactemail", $_POST)==true
		&&array_key_exists("contactphone", $_POST)==true
		&&array_key_exists("contactmessage", $_POST)==true
		&&array_key_exists("g-recaptcha-response", $_POST)==true){
		// first, validate the recaptcha
		$recaptchaResult = crypto::validateRecaptcha($_POST["g-recaptcha-response"]);
		if($recaptchaResult==true){
			// get the e-mail object
			$e = $b->getEmail();

			// check whether the contact request was sent successfully
			// or not and define the notificytion to show 
			if($e->sendContactRequest($_POST["contactemail"],
					$_POST["contactname"],$_POST["contactphone"],
					$_POST["contactmessage"])){
				// e-mail sent successfully, show success notification
				$notificiationMessageCode = "CONTACT_REQUEST_SENT";
			}else{
				// define the error notification message
				$notificiationMessageCode = "CONTACT_REQUEST_FAILED";
			}
		}else{
			// set and error notification for the captcha failure
			$notificiationMessageCode = "CONTACT_CAPTCHA_FAILED";
		}
	}
}

// assign the blog data to the template
$template->assign("categoryList",$categoryPublishedList);

// pass page type and item to the template
$template->assign("pageType",$pageType);
$template->assign("pageItem",$pageItem);

/* set the 404 indicator when 
 * the page is 404 and also add
 * the proper http response code */
if($pageType=="404" || $is_404==true){
	// sets the flag
	$is_404 = true;
	
	/* the 404 page will show a 
	 * list of all articles */
	$template->assign("articleList",
		$b->getLatestArticles(20));
	
	// sets the 404 header
	header("HTTP/1.0 404 Not Found");
}

/* assign the variables that indicates 
 * whether the user logged in or not */
if($u->isNewUser()==true){
	// the user just logged in
	$template->assign("is_new_user","1");
	$template->assign("is_logged_out","0");
}else{
	// the user is either already logged in
	// or is not logged in
	$template->assign("is_new_user","0");
	$template->assign("is_logged_out","0");
	
	// check if there is a logout request
	if(array_key_exists("logout", $_GET)){
		// pass over to the analytics event tracking
		$template->assign("is_logged_out","1");
	}
}

// indicates whether a 
// comment was posted or not
if($comment_posted==true){
	// comment was posted with this request
	$template->assign("comment_posted","1");
}else{
	// no comment was posted with this request
	$template->assign("comment_posted","0");
}

// determine the ip version used for this request
$ipVersion = $b->getIPVersion();

// assign the uqid to the template
$ga = new analytics();
$template->assign("uqid",$ga->getUqId());
$template->assign("ipversion",$ipVersion);

// assign the current year for the legal footer
$template->assign("year",date("Y"));

// assign the language code
$template->assign("languageCode",$b->db->getLanguageCode());

// assign the template values
$template->assign("is_404",$is_404);
$template->assign("loggedIn",$u->isLoggedIn());
$template->assign("user_authprovider",$userAuthProvider);
$template->assign("is_admin",$is_admin);
$template->assign("notification_code",$notificiationMessageCode);

// assign the minpack version tags to 
// prevent users from using outdated minpacks from their cache
$jsMinpackTag = minify::getMinpackTag(CONFIG_MINPACK_JS);
$cssMinpackTag = minify::getMinpackTag(CONFIG_MINPACK_CSS);
$template->assign("minpack_js_tag",$jsMinpackTag);
$template->assign("minpack_css_tag",$cssMinpackTag);

// attach the CDN host names
$template->assign("cdn_host_proxy",CONFIG_CDN_PROXY_DOMAIN);
$template->assign("primary_domain",CONFIG_CDN_PRIMARY_DOMAIN);

$template->assign("cdn_host_js",CONFIG_CDN_JS_DOMAIN);
$template->assign("cdn_host_css",CONFIG_CDN_CSS_DOMAIN);

// attach the google analytics site data
$template->assign("analytics_account",CONFIG_GA_SITE_ACCOUNT);

// fetch the content, minify, remove line breaks and output it
$html_output = $template->fetch("themes/default/master.tpl");

/* update the image tags with the cdn host names */
$html_output = $b->updateCdnHtml($html_output);

/* update the product boxes with the amazon product infos */
$html_output = $b->updateProductListings($html_output);

// set the content type and charset header before output
header("Content-Type: text/html; charset=utf-8");

// finally print out the minified html code
print(minify::minifyHtml($html_output));
?>
